package com.ltu.websocket;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Objects;
import com.ltu.ai.sparkdesk.websocket.AiContextManager;
import com.ltu.ai.sparkdesk.websocket.AiContextManager.IatContext;
import com.ltu.ai.sparkdesk.websocket.legal.LegalSocketService;
import com.ltu.ai.sparkdesk.websocket.ultra.SparkSocketService;
import com.ltu.domain.mp_entity.customize.DeviceEntity;
import com.ltu.domain.mp_entity.customize.SessionInfoEntity;
import com.ltu.domain.mp_entity.customize.SessionRecordEntity;
import com.ltu.enums.SysDict;
import com.ltu.model.response.base.CodeDataResp;
import com.ltu.service.customize.DeviceAdService;
import com.ltu.service.customize.DeviceService;
import com.ltu.service.customize.SessionInfoService;
import com.ltu.service.customize.SessionRecordService;
import com.ltu.service.impl.customize.DeviceAdServiceImpl;
import com.ltu.util.SpringContextHolder;
import com.ltu.util.SpringUtil;
import com.ltu.websocket.respone.WebSocketRespEncoder;

import cn.binarywang.wx.miniapp.api.WxMaService;
import lombok.extern.slf4j.Slf4j;

/**
 * @Description:
 * @author: 若尘
 * @date 2019年6月27日 下午3:23:55
 * @version V1.0
 */
@Slf4j
@Component
@ServerEndpoint(value = "/websocket/{deviceMac}",encoders = {WebSocketRespEncoder.class})
public class WebSocketServer {

    //在线连接数
    private static AtomicInteger  onlineCount = new AtomicInteger(0); 
//	private static ConcurrentMap<String, Session>  SessionManager = new ConcurrentHashMap<String, Session>();  
	private DeviceService deviceService;
	private SessionInfoService sessionInfoService;
	private SparkSocketService sparkSocketService;
	private SessionRecordService sessionRecordService;

	
	/**
	 * 连接建立成功调用的方法
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam("deviceMac") String deviceMac) {
//		SessionManager.put(deviceMac, session); // 加入set中
		deviceMac = decodeDeviceMac(deviceMac);
		this.deviceService  = SpringContextHolder.getBean("deviceServiceImpl");
		DeviceEntity device =	this.deviceService.editOnline(deviceMac, 1);
		if(device == null) {
			log.error("{} 设备不存在",deviceMac);
			this.onClose(session, deviceMac);
		}
		this.sessionInfoService  = SpringContextHolder.getBean("sessionInfoServiceImpl");
		this.sessionRecordService  = SpringContextHolder.getBean("sessionRecordServiceImpl");
		IatContext iatcontext = new AiContextManager.IatContext(deviceMac, session);
		iatcontext.setDeviceEntity(device);
		
		Integer onlineNo =onlineCount.incrementAndGet();//自增
		log.info("设备 :" + deviceMac + "加入,当前在线人数为" + onlineNo);	
		
		SessionInfoEntity entity = new SessionInfoEntity();
		 entity.setDeviceMac(deviceMac)
		 		.setDeviceName(device.getDeviceName())
		 		.setDeviceId(Integer.parseInt(device.getId()))
			   .setStatus("1")
			   .setDevicePosition(device.getDevicePosition())
			   ;
		 entity.setDeviceType(device.getDeviceType());
		 entity.setTotalToken(0);
		 entity.setTotalQuestion(0);
		 sessionInfoService.save(entity);
		 iatcontext.setSessionEntity(entity);
		 AiContextManager.IatContextMap.put(deviceMac, iatcontext);
		 this.sparkSocketService  = SpringContextHolder.getBean("sparkSocketService");
	
		
	}

	@OnClose
	public void onClose(Session session, @PathParam("deviceMac") String deviceMac) {
//		SessionManager.remove(deviceMac);
		deviceMac = decodeDeviceMac(deviceMac);
		Integer onlineNo = onlineCount.decrementAndGet();
		log.info("设备 :" + deviceMac + "关闭,当前在线人数为" + onlineNo);
		this.deviceService.editOnline(deviceMac, 0);
		if(AiContextManager.IatContextMap.containsKey(deviceMac)) {
			SessionInfoEntity entity= AiContextManager.IatContextMap.get(deviceMac).getSessionEntity();
			if(entity !=null) {
				entity.setStatus("0");
				sessionInfoService.updateById(entity);
			}
			if(AiContextManager.IatContextMap.get(deviceMac).getSparkSocketClient()!=null) {
				AiContextManager.IatContextMap.get(deviceMac).getSparkSocketClient().close();
			}
			AiContextManager.IatContextMap.remove(deviceMac);
		}
		
	}
	
	private String decodeDeviceMac(String deviceMac) {
		try {
		String	deviceMac2 = URLDecoder.decode(deviceMac, StandardCharsets.UTF_8.name());
			return deviceMac2;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 收到客户端消息后调用的方法
	 *	
	 * @param message  
	 *         心跳  { heartbeat: 1 }
	 *        提问   {content: xx , action :"relQuestion"}
	 * @throws InterruptedException 
	 */
	@OnMessage
	public void onMessage(String message, Session session, @PathParam("deviceMac") String deviceMac) {
		deviceMac = decodeDeviceMac(deviceMac);
		log.info("收到设备：" + deviceMac + "的信息:" + message);	
		JSONObject  req = JSONObject.parseObject(message);
		if(req.containsKey("heartbeat")) 
			return;
		IatContext iatContext =	AiContextManager.IatContextMap.get(deviceMac);
		if(iatContext == null) 
			return;
		String action = "";
		if(req.containsKey("action"))
			action = req.getString("action");
		if(StringUtils.equals(action, "relQuestion")) {
			 String  question =  req.getString("content");
			 SessionRecordEntity record = new SessionRecordEntity();
		    	record.setDeviceMac(deviceMac)
		    		  .setContent(question)
		    		  .setRole(SysDict.SessionRole.Client.getName())
		    		  .setCreateTime(new Date())
		    		  .setSessionId(Integer.parseInt(iatContext.getSessionEntity().getId()))
		    	;
		    		sessionRecordService.save(record);
			 if(iatContext.getSparkSocketClient()!=null) {
				 sparkSocketService.sendQuestion(iatContext.getSparkSocketClient(),question);
             }else {
            	 sparkSocketService.createAIClient(iatContext.getDeviceMac());
             }
			
		}
		
	}

	/**
	 * 
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error, @PathParam("deviceMac") String deviceMac) {
		deviceMac = decodeDeviceMac(deviceMac);
		System.out.println(error.getMessage());
		log.error("设备：{},发生错误{}",deviceMac,error.getMessage());
		if(AiContextManager.IatContextMap.containsKey(deviceMac)) {
			SessionInfoEntity entity= AiContextManager.IatContextMap.get(deviceMac).getSessionEntity();
			if(entity !=null) {
				entity.setStatus("0");
				sessionInfoService.updateById(entity);
			}
			AiContextManager.IatContextMap.remove(deviceMac);
		}
		
		error.printStackTrace();
	}

    
    /**
     * 实现服务器主动推送
     */
    public static void sendMessage(String obj, String deviceMac) throws IOException, EncodeException {
    	  Session session = AiContextManager.IatContextMap.get(deviceMac).getDeviceClient();
          if(!ObjectUtils.isEmpty(session)) {
              if (session.isOpen()) {
                  session.getBasicRemote().sendText(obj);
              } else {
            	  AiContextManager.IatContextMap.remove(deviceMac);
            	  log.error("deviceNo设备已断开，停止发送消息");
              }
          }
    }
	
    /**
     * @Description: 获取在线连接数
     * @author 李生
     * @date 2024-10-16 06:48:34 
     * @return
     */
    public static  int getOnlineCount() {
        return onlineCount.get();
    }
    
    
    

}
